#include "scu.h"
#include "riscv-it.h"

SCU_t *const SCU = (SCU_t *)SCU_BASE_ADDR;

void scu_init(SCU_t *SCU)
{

    // // ACPU pll clk configure PLL_CTRL_0
    // set_acpu_pll_ctrl_0_acpu_foutpostdiven(SCU, 0x1);
    // set_acpu_pll_ctrl_0_acpu_fouten(SCU, 0x1);
    // // set_acpu_pll_ctrl_0_acpu_fbdiv(SCU, 0x50);//0x50: 1600MHz
    // set_acpu_pll_ctrl_0_acpu_fbdiv(SCU, 0x28);//0x28: 800MHz
    // set_acpu_pll_ctrl_0_acpu_refdiv(SCU, 0x1);
    // set_acpu_pll_ctrl_0_acpu_postdiv1(SCU, 0x1);
    // SCU->ACPU_PLL_CTRL_1 = 0x00000000;
    // SCU->ACPU_PLL_CTRL_2 = 0x00000000;
    // SCU->ACPU_PLL_CTRL_3 = 0x00000000;
    // SCU->ACPU_PLL_CTRL_4 |= ACPU_PLL_CTRL_4_ACPU_PLLEN | ACPU_PLL_CTRL_4_ACPU_PLL_CHANGE_FREQ;

    // while(!(get_acpu_pll_status_acpu_lock(SCU)));

    // MEM pll clk configure PLL_CTRL_0
    set_memory_pll_ctrl_0_mem_foutpostdiven(SCU, 0x1);
    set_memory_pll_ctrl_0_mem_fouten(SCU, 0x1);
    set_memory_pll_ctrl_0_mem_fout4phaseen(SCU, 0x1);
    set_memory_pll_ctrl_0_mem_fbdiv(SCU, 0x50);
    set_memory_pll_ctrl_0_mem_refdiv(SCU, 0x1);
    set_memory_pll_ctrl_0_mem_postdiv1(SCU, 0x1);
    // SCU->MEMORY_PLL_CTRL_0 = ;
    SCU->MEMORY_PLL_CTRL_1 = 0x00000000;
    SCU->MEMORY_PLL_CTRL_2 = 0x00000000;
    SCU->MEMORY_PLL_CTRL_3 = 0x00000000;
    SCU->MEMORY_PLL_CTRL_4 |= MEMORY_PLL_CTRL_4_MEM_PLL_CHANGE_FREQ | MEMORY_PLL_CTRL_4_MEM_PLLEN;

    while(!(get_mem_pll_status_mem_lock(SCU)));

    // HS pll clk configure PLL_CTRL_0
    set_hs_pll_ctrl_0_hs_foutpostdiven(SCU, 0x1);
    set_hs_pll_ctrl_0_hs_fouten(SCU, 0x1);
    set_hs_pll_ctrl_0_hs_fout4phaseen(SCU, 0x1);
    set_hs_pll_ctrl_0_hs_fbdiv(SCU, 0x32);
    set_hs_pll_ctrl_0_hs_refdiv(SCU, 0x1);
    set_hs_pll_ctrl_0_hs_postdiv1(SCU, 0x1);
    SCU->HS_PLL_CTRL_1 = 0x00000000;
    SCU->HS_PLL_CTRL_2 = 0x00000000;
    SCU->HS_PLL_CTRL_3 = 0x00000000;
    SCU->HS_PLL_CTRL_4 |= HS_PLL_CTRL_4_HS_PLLEN | HS_PLL_CTRL_4_HS_PLL_CHANGE_FREQ;

    while(!(get_hs_pll_status_lock(SCU)));

    SCU->GATING_CONTROL |= GATING_CONTROL_CG_ACPU | GATING_CONTROL_CG_HS | GATING_CONTROL_CG_MEM;
    SCU->GATING_CONTROL |= GATING_CONTROL_CG_HS | GATING_CONTROL_CG_MEM;

	set_ext_addr_ext_addr(SCU, 0x40);

    SCU->SW_RST_CONTROL = 0x1f3ff;
    //SCU->SW_RST_CONTROL = 0xfffff3ff;
    //SCU->SW_RST_CONTROL = 0xfffff3ff;
    // SCU->SW_RST_CONTROL = 0x000173ff;
    SCU->SW_RST_CONTROL = 0xfffff3ff;

    disable_interrupt(WDT_INTERRUPT_SRC, ACPU_DEST);
    // enable_interrupt(GP_TIMER_INTERRUPT_SRC, ACPU_DEST);
    // enable_interrupt(BOOT_SSI_INTERRUPT_SRC, ACPU_DEST);
    enable_interrupt(GP_SSI_INTERRUPT_SRC, ACPU_DEST);
    enable_interrupt(MAILBOX_INTERRUPT_SRC, ACPU_DEST);
    enable_interrupt(UART_INTERRUPT_SRC, ACPU_DEST);
    enable_interrupt(I2C_INTERRUPT_SRC, ACPU_DEST);
    enable_interrupt(GBE0_INTERRUPT_SRC, ACPU_DEST);
    enable_interrupt(GBE1_INTERRUPT_SRC, ACPU_DEST);
    enable_interrupt(USB0_INTERRUPT_SRC, ACPU_DEST);
    enable_interrupt(USB1_INTERRUPT_SRC, ACPU_DEST);
    
    interrupt_plic_init();

}
